import { promises as fs } from 'fs';
import path from 'path';
import xml2js from 'xml2js';

import { translateRecursiveTrim } from '../translations';

async function parseFile(pathToFile) {
  const parser = new xml2js.Parser({ mergeAttrs: true, explicitArray: false });
  return await parser.parseStringPromise(await fs.readFile(pathToFile));
}

export async function processFactions(sourceBasePath, translations) {
  const baseSourcePath = sourceBasePath;
  const splitSourcePath = path.join(sourceBasePath, 'extensions', 'ego_dlc_split');
  const terranSourcePath = path.join(sourceBasePath, 'extensions', 'ego_dlc_terran');
  const pirateSourcePath = path.join(sourceBasePath, 'extensions', 'ego_dlc_pirate');
  const boronSourcePath = path.join(sourceBasePath, 'extensions', 'ego_dlc_boron');

  let factions = [...(await parseFile(path.join(baseSourcePath, 'libraries', 'factions.xml'))).factions.faction];

  let splitFactions = (await parseFile(path.join(splitSourcePath, 'libraries', 'factions.xml'))).diff.add;
  splitFactions.forEach((addStatement) => {
    if (addStatement.sel === '/factions') {
      factions = factions.concat(addStatement.faction);
    } else {
      const regex = /'(.*?)'/g;
      const match = [...addStatement.sel.matchAll(regex)].map((m) => m[1]);
      factions.forEach((faction) => {
        if (faction.id === match[0]) {
          if (addStatement.relation)
            faction.relations.relation = faction.relations.relation.concat(addStatement.relation);
        }
      });
    }
  });

  let terranFactions = (await parseFile(path.join(terranSourcePath, 'libraries', 'factions.xml'))).diff.add;
  terranFactions.forEach((addStatement) => {
    if (addStatement.sel === '/factions') {
      factions = factions.concat(addStatement.faction);
    } else {
      const regex = /'(.*?)'/g;
      const match = [...addStatement.sel.matchAll(regex)].map((m) => m[1]);
      factions.forEach((faction) => {
        if (faction.id === match[0]) {
          if (addStatement.relation)
            faction.relations.relation = faction.relations.relation.concat(addStatement.relation);
        }
      });
    }
  });

  let pirateFactions = (await parseFile(path.join(pirateSourcePath, 'libraries', 'factions.xml'))).diff.add;
  pirateFactions.forEach((addStatement) => {
    if (addStatement.sel === '/factions') {
      factions = factions.concat(addStatement.faction);
    } else {
      const regex = /'(.*?)'/g;
      const match = [...addStatement.sel.matchAll(regex)].map((m) => m[1]);
      factions.forEach((faction) => {
        if (faction.id === match[0]) {
          if (addStatement.relation)
            faction.relations.relation = faction.relations.relation.concat(addStatement.relation);
        }
      });
    }
  });

  let boronFactions = (await parseFile(path.join(boronSourcePath, 'libraries', 'factions.xml'))).diff.add;
  boronFactions.forEach((addStatement) => {
    if (addStatement.sel === '/factions') {
      factions = factions.concat(addStatement.faction);
    } else {
      const regex = /'(.*?)'/g;
      const match = [...addStatement.sel.matchAll(regex)].map((m) => m[1]);
      factions.forEach((faction) => {
        if (faction.id === match[0]) {
          if (addStatement.relation)
            faction.relations.relation = faction.relations.relation.concat(addStatement.relation);
        }
      });
    }
  });

  const relationsLookup = {};

  factions = factions
    .filter(
      (faction) =>
        faction.id !== 'ownerless' &&
        faction.id !== 'smuggler' &&
        faction.id !== 'civilian' &&
        faction.id !== 'criminal' &&
        faction.id !== 'visitor'
    )
    .map((faction) => {
      faction.name = translateRecursiveTrim(faction.name, translations);
      faction.description = translateRecursiveTrim(faction.description, translations);
      faction.shortname = translateRecursiveTrim(faction.shortname, translations);
      faction.prefixname = translateRecursiveTrim(faction.prefixname, translations);

      relationsLookup[faction.id] = {
        shortname: faction.shortname,
        willExpand: faction.tags.indexOf('claim') !== -1,
        relations: {},
      };

      faction.relations.relation.forEach((relationItem) => {
        const relation = parseFloat(relationItem.relation);
        const isNegative = relation < 0;
        const relationForLog = isNegative ? relation * -1 : relation;

        let uiValue = 10 * Math.log10(relationForLog * 1000);
        relationsLookup[faction.id].relations[relationItem.faction] = Math.round(isNegative ? uiValue * -1 : uiValue);
      });

      return faction;
    });

  return {
    relationsLookup: relationsLookup,
    data: factions,
  };
}
